///////////////////////  comments  /////////////////

#include <vector>
#include "command.h"
#include "commandTable.h"
#include "definitions.h"
#include "stringutil.h"
#include "world.h"

/////////////////////////////////////// regular command table //////////////////////////////////////

// Constructor...
CommandTable::CommandTable( void ) {
	loadCommands();	
}

// Destructor...
CommandTable::~CommandTable( void ) {
	for ( std::vector< Command* >::iterator it = getCommands().begin(); it != getCommands().end(); ) {
		delete (*it);
		it = getCommands().erase( it );
	}
}

// Protected methods...
void CommandTable::add( Command* command ) { // protected
	getCommands().push_back( command );
	return;
}

bool CommandTable::loadCommands( void ) { // protected
	// Populate list with commands
	// Keep in alphabetical order, except directional commands,
	// They should go first within that letter. That way, users
	// can type "n" for north, "e" for east, etc...
	add( new CmdAedit );
	add( new CmdAlist );
	add( new CmdAsave );
	add( new CmdAt );
	add( new CmdBoards );
	add( new CmdBuzz );
	add( new CmdClear );
	add( new CmdClose );
	add( new CmdColors );
	add( new CmdCommands );
	add( new CmdDown );
	add( new CmdDemote );
	add( new CmdDescription );
	add( new CmdDisable );
	add( new CmdDisconnect );
	add( new CmdDrop );
	add( new CmdEast );
	add( new CmdEat );
	add( new CmdEmote );
	add( new CmdEnable );
	add( new CmdForce );
	add( new CmdGecho );
	add( new CmdGet );
	add( new CmdGive );
	add( new CmdGoto );
	add( new CmdHelp );
	add( new CmdInformation );
	add( new CmdInventory );
	add( new CmdLook );
	add( new CmdMedit );
	add( new CmdMlist );
//	add( new CmdMload );
	add( new CmdNorth );
//	add( new CmdNotes );
//	add( new CmdOedit );
//	add( new CmdOlist );
//	add( new CmdOload );
	add( new CmdOmninet );
	add( new CmdOmniset );
	add( new CmdOpen );
	add( new CmdPassword );
	add( new CmdPedit );
	add( new CmdPoofin );
	add( new CmdPoofout );
	add( new CmdPoofs );
	add( new CmdPromote );
	add( new CmdPrompt );
	add( new CmdQuit );
	add( new CmdReboot );
	add( new CmdRedit );
	add( new CmdReply );
	add( new CmdSouth );
	add( new CmdSave );
	add( new CmdSay );
	add( new CmdScore );
	add( new CmdShutdown );
//	add( new CmdSiteban );
	add( new CmdSockets );
	add( new CmdSummon );
	add( new CmdTake );
	add( new CmdTell );
	add( new CmdTimers );
	add( new CmdTitle );
	add( new CmdTransport );
	add( new CmdUp );
	add( new CmdWest );
	add( new CmdWho );
	add( new CmdWhos );
	return true;
}

// Public accessor methods...
std::vector< Command* >& CommandTable::getCommands( void ) { // public
	return _commands;
}

// General methods...
Command* CommandTable::findCommand( Character* character, const std::string& command ) { // public
	std::string command1 = trim( command );

	for ( std::vector< Command* >::iterator it = getCommands().begin(); it != getCommands().end(); ++it ) {
		if ( (*it)->getName() == command1 || str_prefix( command1, (*it)->getName() ) ) {
			// Check level-based permissions.
			if ( (*it)->getLevel() > character->getLevel() || !(*it)->getEnabled() ) {
				character->Send( "Huh?" );
				return NULL;
			} else {
				return (*it);
			}
		}
	}

	character->Send( "Huh?" );
	return NULL;
}

bool CommandTable::execute( Character* character, const std::string& commandAndArgs ) { // public
	std::string input = trim( commandAndArgs );
	std::string s_command;
	std::string arguments;
	std::string buf;
	Command* command = NULL;

	if ( input.empty() )
		return false;

	split( input, s_command, arguments );
	s_command = trim( s_command );
	arguments = trim( arguments );

	if ( ( command = findCommand( character, s_command ) ) != NULL ) {
		if ( command->getOmniset()  );
			World::Instance().omninet( character->getName() + ": " + command->getName() + " " + arguments, character );
		command->execute( character, arguments );
		return true;
	}

	return false;
}

/////////////////////////////////////// area edit mode command table //////////////////////////////////////

// Constructor...
aCommandTable::aCommandTable( void ) {
	loadCommands();	
}

// Destructor...
aCommandTable::~aCommandTable( void ) {
	for ( std::vector< Command* >::iterator it = getCommands().begin(); it != getCommands().end(); ) {
		delete (*it);
		it = getCommands().erase( it );
	}
}

// Protected methods...
void aCommandTable::add( Command* command ) { // protected
	getCommands().push_back( command );
	return;
}

bool aCommandTable::loadCommands( void ) { // protected
	// Populate list with commands; keep in alphabetical order.

	// First add in basic Commands...
	add( new CmdAlist );
	add( new CmdGecho );
	add( new CmdReply );
	add( new CmdTell );
	add( new CmdSay );

	// Add in aedit Commands...
	add( new aCmdCommands );
	add( new aCmdExit );
	add( new aCmdKeyword );
	add( new aCmdList );
	add( new aCmdMake );
	add( new aCmdName );
	add( new aCmdPermissions );
	add( new aCmdRemove );
	add( new aCmdSelect );
	add( new aCmdView );

	return true;
}

// Public accessor methods...
std::vector< Command* >& aCommandTable::getCommands( void ) { // public
	return _commands;
}

// General methods...
Command* aCommandTable::findCommand( Character* character, const std::string& command ) { // public
	std::string command1 = trim( command );

	for ( std::vector< Command* >::iterator it = getCommands().begin(); it != getCommands().end(); ++it ) {
		if ( (*it)->getName() == command1 || str_prefix( command1, (*it)->getName() ) ) {
			// Check level-based permissions.
			if ( (*it)->getLevel() > character->getLevel() || !(*it)->getEnabled() ) {
				character->Send( "Huh?" );
				return NULL;
			} else {
				return (*it);
			}
		}
	}

	character->Send( "Huh?" );
	return NULL;
}

bool aCommandTable::execute( Character* character, const std::string& commandAndArgs ) { // public
	std::string input = trim( commandAndArgs );
	std::string s_command;
	std::string arguments;
	std::string buf;
	Command* command = NULL;

	if ( input.empty() )
		return false;

	split( input, s_command, arguments );
	s_command = trim( s_command );
	arguments = trim( arguments );

	if ( ( command = findCommand( character, s_command ) ) != NULL ) {
		if ( command->getOmniset()  );
			World::Instance().omninet( character->getName() + ": " + command->getName() + " " + arguments, character );
		command->execute( character, arguments );
		return true;
	}

	return false;
}

/////////////////////////////////////// mob edit mode command table //////////////////////////////////////

// Constructor...
mCommandTable::mCommandTable( void ) {
	loadCommands();	
}

// Destructor...
mCommandTable::~mCommandTable( void ) {
	for ( std::vector< Command* >::iterator it = getCommands().begin(); it != getCommands().end(); ) {
		delete (*it);
		it = getCommands().erase( it );
	}
}

// Protected methods...
void mCommandTable::add( Command* command ) { // protected
	getCommands().push_back( command );
	return;
}

bool mCommandTable::loadCommands( void ) { // protected
	// Populate list with commands; keep in alphabetical order.

	// First add in basic Commands...
	add( new CmdGecho );
	add( new CmdReply );
	add( new CmdTell );
	add( new CmdSay );

	// Add in aedit Commands...
	add( new mCmdAc );
	add( new mCmdAcBash );
	add( new mCmdAcSlash );
	add( new mCmdAcPierce );
	add( new mCmdAcExotic );
	add( new mCmdCharisma );
	add( new mCmdClass );
	add( new mCmdCommands );
	add( new mCmdConstitution );
	add( new mCmdDamroll );
	add( new mCmdDescription );
	add( new mCmdDexterity );
	add( new mCmdExit );
	add( new mCmdGender );
	add( new mCmdHp );
	add( new mCmdHitroll );
	add( new mCmdIntelligence );
	add( new mCmdLevel );
	add( new mCmdLong );
	add( new mCmdMana );
	add( new mCmdMove );
	add( new mCmdName );
	add( new mCmdRace );
	add( new mCmdSaves );
	add( new mCmdShort );
	add( new mCmdStrength );
	add( new mCmdView );
	add( new mCmdWimpy );
	add( new mCmdWisdom );
	return true;
}

// Public accessor methods...
std::vector< Command* >& mCommandTable::getCommands( void ) { // public
	return _commands;
}

// General methods...
Command* mCommandTable::findCommand( Character* character, const std::string& command ) { // public
	std::string command1 = trim( command );

	for ( std::vector< Command* >::iterator it = getCommands().begin(); it != getCommands().end(); ++it ) {
		if ( (*it)->getName() == command1 || str_prefix( command1, (*it)->getName() ) ) {
			// Check level-based permissions.
			if ( (*it)->getLevel() > character->getLevel() || !(*it)->getEnabled() ) {
				character->Send( "Huh?" );
				return NULL;
			} else {
				return (*it);
			}
		}
	}

	character->Send( "Huh?" );
	return NULL;
}

bool mCommandTable::execute( Character* character, const std::string& commandAndArgs ) { // public
	std::string input = trim( commandAndArgs );
	std::string s_command;
	std::string arguments;
	std::string buf;
	Command* command = NULL;

	if ( input.empty() )
		return false;

	split( input, s_command, arguments );
	s_command = trim( s_command );
	arguments = trim( arguments );

	if ( ( command = findCommand( character, s_command ) ) != NULL ) {
		if ( command->getOmniset()  );
			World::Instance().omninet( character->getName() + ": " + command->getName() + " " + arguments, character );
		command->execute( character, arguments );
		return true;
	}

	return false;
}

/////////////////////////////////////// player edit mode command table //////////////////////////////////////

// Constructor...
pCommandTable::pCommandTable( void ) {
	loadCommands();	
}

// Destructor...
pCommandTable::~pCommandTable( void ) {
	for ( std::vector< Command* >::iterator it = getCommands().begin(); it != getCommands().end(); ) {
		delete (*it);
		it = getCommands().erase( it );
	}
}

// Protected methods...
void pCommandTable::add( Command* command ) { // protected
	getCommands().push_back( command );
	return;
}

bool pCommandTable::loadCommands( void ) { // protected
	// Populate list with commands; keep in alphabetical order.

	// First add in basic Commands...
	add( new CmdGecho );
	add( new CmdReply );
	add( new CmdTell );
	add( new CmdSay );
	add( new CmdWho );

	// Add in aedit Commands...
	add( new pCmdAge );
	add( new pCmdCommands );
	add( new pCmdExit );
	add( new pCmdEcho );
	add( new pCmdGender );
	add( new pCmdLname );
	add( new pCmdName );

	return true;
}

// Public accessor methods...
std::vector< Command* >& pCommandTable::getCommands( void ) { // public
	return _commands;
}

// General methods...
Command* pCommandTable::findCommand( Character* character, const std::string& command ) { // public
	std::string command1 = trim( command );

	for ( std::vector< Command* >::iterator it = getCommands().begin(); it != getCommands().end(); ++it ) {
		if ( (*it)->getName() == command1 || str_prefix( command1, (*it)->getName() ) ) {
			// Check level-based permissions.
			if ( (*it)->getLevel() > character->getLevel() || !(*it)->getEnabled() ) {
				character->Send( "Huh?" );
				return NULL;
			} else {
				return (*it);
			}
		}
	}

	character->Send( "Huh?" );
	return NULL;
}

bool pCommandTable::execute( Character* character, const std::string& commandAndArgs ) { // public
	std::string input = trim( commandAndArgs );
	std::string s_command;
	std::string arguments;
	std::string buf;
	Command* command = NULL;

	if ( input.empty() )
		return false;

	split( input, s_command, arguments );
	s_command = trim( s_command );
	arguments = trim( arguments );

	if ( ( command = findCommand( character, s_command ) ) != NULL ) {
		if ( command->getOmniset()  );
			World::Instance().omninet( character->getName() + ": " + command->getName() + " " + arguments, character );
		command->execute( character, arguments );
		return true;
	}

	return false;
}

/////////////////////////////////////// room edit mode command table //////////////////////////////////////

// Constructor...
rCommandTable::rCommandTable( void ) {
	loadCommands();	
}

// Destructor...
rCommandTable::~rCommandTable( void ) {
	for ( std::vector< Command* >::iterator it = getCommands().begin(); it != getCommands().end(); ) {
		delete (*it);
		it = getCommands().erase( it );
	}
}

// Protected methods...
void rCommandTable::add( Command* command ) { // protected
	getCommands().push_back( command );
	return;
}

bool rCommandTable::loadCommands( void ) { // protected
	// Populate list with commands; keep in alphabetical order.

	// First add in basic Commands...
	add( new CmdDown );
	add( new CmdEast );
	add( new CmdGecho );
	add( new CmdGoto );
	add( new CmdLook );
	add( new CmdNorth );
	add( new CmdReply );
	add( new CmdTell );
	add( new CmdSouth );
	add( new CmdSay );
	add( new CmdUp );
	add( new CmdWest );

	// Add in redit Commands...
	add( new rCmdCommands );
	add( new rCmdDescription );
	add( new rCmdDig );
	add( new rCmdExit );
	add( new rCmdInfo );
	add( new rCmdLink );
	add( new rCmdMake );
	add( new rCmdName );
	add( new rCmdRemove );
	add( new rCmdReset );
	add( new rCmdRlist );
	add( new rCmdSector );
	add( new rCmdUnlink );
	return true;
}

// Public accessor methods...
std::vector< Command* >& rCommandTable::getCommands( void ) { // public
	return _commands;
}

// General methods...
Command* rCommandTable::findCommand( Character* character, const std::string& command ) { // public
	std::string command1 = trim( command );

	for ( std::vector< Command* >::iterator it = getCommands().begin(); it != getCommands().end(); ++it ) {
		if ( (*it)->getName() == command1 || str_prefix( command1, (*it)->getName() ) ) {
			// Check level-based permissions.
			if ( (*it)->getLevel() > character->getLevel() || !(*it)->getEnabled() ) {
				character->Send( "Huh?" );
				return NULL;
			} else {
				return (*it);
			}
		}
	}

	character->Send( "Huh?" );
	return NULL;
}

bool rCommandTable::execute( Character* character, const std::string& commandAndArgs ) { // public
	std::string input = trim( commandAndArgs );
	std::string s_command;
	std::string arguments;
	std::string buf;
	Command* command = NULL;

	if ( input.empty() )
		return false;

	split( input, s_command, arguments );
	s_command = trim( s_command );
	arguments = trim( arguments );

	if ( ( command = findCommand( character, s_command ) ) != NULL ) {
		if ( command->getOmniset()  );
			World::Instance().omninet( character->getName() + ": " + command->getName() + " " + arguments, character );
		command->execute( character, arguments );
		return true;
	}

	return false;
}

/////////////////////////////////////// text editor mode command table //////////////////////////////////////

// Constructor...
tCommandTable::tCommandTable( void ) {
	loadCommands();	
}

// Destructor...
tCommandTable::~tCommandTable( void ) {
	for ( std::vector< Command* >::iterator it = getCommands().begin(); it != getCommands().end(); ) {
		delete (*it);
		it = getCommands().erase( it );
	}
}

// Protected methods...
void tCommandTable::add( Command* command ) { // protected
	getCommands().push_back( command );
	return;
}

bool tCommandTable::loadCommands( void ) { // protected
	// Populate list with commands; keep in alphabetical order.

	// Add in text editor Commands...
	add( new tCmdAdd );
	add( new tCmdExit );
	add( new tCmdHelp );
	add( new tCmdInsert );
	add( new tCmdRemove );
	add( new tCmdReplace );

	return true;
}

// Public accessor methods...
std::vector< Command* >& tCommandTable::getCommands( void ) { // public
	return _commands;
}

// General methods...
Command* tCommandTable::findCommand( Character* character, const std::string& command ) { // public
	std::string command1 = trim( command );

	for ( std::vector< Command* >::iterator it = getCommands().begin(); it != getCommands().end(); ++it ) {
		if ( (*it)->getName() == command1 || str_prefix( command1, (*it)->getName() ) ) {
			// Check level-based permissions.
			if ( (*it)->getLevel() > character->getLevel() || !(*it)->getEnabled() ) {
				character->Send( "Huh?" );
				return NULL;
			} else {
				return (*it);
			}
		}
	}

	character->Send( "Huh?" );
	return NULL;
}

bool tCommandTable::execute( Character* character, const std::string& commandAndArgs ) { // public
	std::string input = trim( commandAndArgs );
	std::string s_command;
	std::string arguments;
	std::string buf;
	Command* command = NULL;

	if ( input.empty() )
		return false;

	split( input, s_command, arguments );
	s_command = trim( s_command );
	arguments = trim( arguments );

	if ( ( command = findCommand( character, s_command ) ) != NULL ) {
		if ( command->getOmniset()  );
			World::Instance().omninet( character->getName() + ": " + command->getName() + " " + arguments, character );
		command->execute( character, arguments );
		return true;
	}

	return false;
}
